#ifndef cathlibcpp_ostream_H
#define cathlibcpp_ostream_H

// File:       ostream.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ ostream header


#ifndef cathlibcpp_bool_H
#include "bool.h"
#endif

#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_ios_H
#include "ios.h"
#endif

#ifndef cathlibcpp_newcasts_H
#include "newcasts.h"
#endif

#ifndef cathlibcpp_string_H
#include "string.h"              // for char_traits_char
#endif


class basic_ostream_char;
typedef basic_ostream_char ostream;

class basic_ostream_char : virtual public basic_ios_char
{
  friend class OStreamCommand;
  friend class InsertStreamBufCommand;
  friend class basic_ostream_char_sentry;

  public:

    // types
    typedef char_traits_char traits;

    // constructors
    basic_ostream_char(basic_streambuf_char* sb);
    virtual ~basic_ostream_char();

    // formatted output
    basic_ostream_char& operator<<(basic_ostream_char& (*pf)(basic_ostream_char&));
    basic_ostream_char& operator<<(basic_ios_char& (*pf)(basic_ios_char&));
    basic_ostream_char& operator<<(ios_base& (*pf)(ios_base&));

#ifdef BUILTIN_BOOL
    basic_ostream_char& operator<<(bool n);
#endif
    basic_ostream_char& operator<<(short n);
    basic_ostream_char& operator<<(unsigned short n);
    basic_ostream_char& operator<<(int n);
    basic_ostream_char& operator<<(unsigned int n);
    basic_ostream_char& operator<<(long n);
    basic_ostream_char& operator<<(unsigned long n);
    basic_ostream_char& operator<<(float f);
    basic_ostream_char& operator<<(double f);

    basic_ostream_char& operator<<(void* p);

    basic_ostream_char& operator<<(basic_streambuf_char* sb);

    // unformatted output
    basic_ostream_char& put(char c);
    basic_ostream_char& write(char const* s, streamsize n);

    basic_ostream_char& flush();

    int tellp();
    basic_ostream_char& seekp(int pos);
    basic_ostream_char& seekp(int off, seekdir dir);

  private:

    // not implemented
    basic_ostream_char(basic_ostream_char const&);
    basic_ostream_char& operator=(basic_ostream_char const&);
};


basic_ostream_char& operator<<(basic_ostream_char&os, char c);
basic_ostream_char& operator<<(basic_ostream_char&os, unsigned char c);

basic_ostream_char& operator<<(basic_ostream_char& os, char const* s);
basic_ostream_char& operator<<(basic_ostream_char& os, unsigned char const* s);

basic_ostream_char& endl(basic_ostream_char& os);
basic_ostream_char& ends(basic_ostream_char& os);
basic_ostream_char& flush(basic_ostream_char& os);


class basic_ostream_char_sentry
{
  public:

    basic_ostream_char_sentry(basic_ostream_char& os);
    ~basic_ostream_char_sentry();

    operator bool()
      { return ok_; }

  private:

    basic_ostream_char& os_;
    bool ok_;
};


// Implementation of basic_ostream_char

inline basic_ostream_char& basic_ostream_char::operator<<(basic_ostream_char& (*pf)(basic_ostream_char&))
  { return pf(*this); }

inline basic_ostream_char& basic_ostream_char::operator<<(basic_ios_char& (*pf)(basic_ios_char&))
  {
    pf(*this);
    return *this;
  }

inline basic_ostream_char& basic_ostream_char::operator<<(ios_base& (*pf)(ios_base&))
  {
    pf(*this);
    return *this;
  }


// implementation of basic_ostream_char free fns

inline basic_ostream_char& operator<<(basic_ostream_char& os, unsigned char c)
{
  return operator<<(os, reinterpret_cast(char, c));
}

inline basic_ostream_char& operator<<(basic_ostream_char& os, unsigned char const* s)
{
  return operator<<(os, reinterpret_cast(char const*, s));
}

#endif
